<template>
  <BasicDrawer
    v-bind="$attrs"
    @register="registerDrawer"
    showFooter
    width="1200px"
    @ok="handleSubmit"
  >
    <Card title="基本信息" :bordered="false" class="!mt-5">
      <BasicForm @register="register">
      </BasicForm>
    </Card>
    <Card title="参数管理" :bordered="false" class="!mt-5">
      <FieldTable v-if="loadTable" ref="tableRef" :data="tableData" :standardModelFieldOptions="standardModelFieldOptions" />
    </Card>
  </BasicDrawer>
</template>
<script lang="ts" setup>
  import { ref, unref } from 'vue';
  import { BasicForm, useForm, FormSchema } from '@/components/Form';
  import { Card } from 'ant-design-vue';
  import { BasicDrawer, useDrawerInner } from '@/components/Drawer';
  import FieldTable from './FieldTable.vue';
  import { createEntity, editEntity } from '@/api/entity'
  import { getDBList, getTableList, getColumnList } from '@/api/datasource'
  import { getStandardModelList } from '@/api/standardModel'

  const sourceDBOptions = ref([]);
  const tableOptions = ref([]);
  const fieldOptions = ref([]);
  const standardModelFieldOptions = ref([]);

  const basicSchemas: FormSchema[] = [
    {
      field: 'source_db',
      label: '数据库',
      required: true,
      component: 'Select',
      componentProps: ({ formModel }) => {
        return {
          options: sourceDBOptions.value,
          onChange: (e) => {
            formModel.table = undefined;
            refreshTableList(e);
          },
        }
      },
    },
    {
        field: 'source_table',
        label: '数据表',
        required: false,
        colProps: {
          offset: 2,
        },
        component: 'Select',
        componentProps: ({ formModel }) => {
          return {
            options: tableOptions.value,
            onChange: (e) => {
              if (!isUpdate.value) {
                initFields(formModel.source_db, e, formModel);
              }
            },
          }
        },
      },
    {
      field: 'standard_model',
      label: '标准模型',
      required: false,
      colProps: {
        offset: 2,
      },
      component: 'ApiSelect',
      componentProps: ({ formModel }) => {
        return {
          api: getStandardModelList,
          params: {},
          resultField: 'items',
          labelField: 'label',
          valueField: 'value',
          immediate: true,
          onChange: (e, v) => {
            if (v) {
              standardModelFieldOptions.value = v.fields;
            }
          },
        }
      },
    },
    {
      field: 'name',
      label: '名称',
      required: true,
      component: 'Input',
    },
    {
      field: 'key',
      label: 'Key',
      required: true,
      component: 'Input',
      colProps: {
        offset: 2,
      },
    },
    {
      field: 'primary_key',
      label: '指定主键',
      required: true,
      component: 'Input',
      colProps: {
        offset: 2,
      },
    },
    {
      field: 'source_updated_at_field',
      label: '指定更新时间字段',
      required: false,
      component: 'Select',
      componentProps: {
        options: fieldOptions,
      },
    },
    {
      field: 'sql_filter',
      label: 'sql过滤器',
      required: false,
      component: 'Input',
      colProps: {
        offset: 2,
        span: 14,
      },
    },
  ];

  const [register, { resetFields, setFieldsValue, validate }] = useForm({
    layout: 'vertical',
    baseColProps: {
      span: 6,
    },
    schemas: basicSchemas,
    showActionButtonGroup: false,
  });

  const emit = defineEmits(['success', 'register']);
  const isUpdate = ref(true);
  const id = ref();
  const tableRef = ref<{ getDataSource: () => any, initRows: (rows: any[]) => any } | null>(null);
  const tableData = ref([]);
  const loadTable = ref(false);

  const [registerDrawer, { setDrawerProps, closeDrawer }] = useDrawerInner(async (data) => {
    isUpdate.value = data?.isUpdate;
    id.value = data?.record?.id;
    tableData.value = data?.record?.fields;
    loadTable.value = true;
    await getSourceDBOptions();
    resetFields();
    setDrawerProps({ confirmLoading: true });
    if (unref(isUpdate)) {
      setFieldsValue({
        ...data.record,
      });
    }
    setDrawerProps({ confirmLoading: false });
  });

  async function handleSubmit() {
    try {
      const values = await validate();
      const fields: any[] = [];
      if (tableRef.value) {
        const tableRows = tableRef.value.getDataSource();
        for (const row of tableRows) {
          const field = {
            field: row.field,
            label: row.label,
            source_field: row.source_field,
            standard_model_field: row.standard_model_field,
          };
          fields.push(field);
        }
      }
      values.fields = fields;
      if (unref(isUpdate)) {
        await editEntity(id.value, values);
      } else {
        await createEntity(values);
      }
      closeDrawer();
      emit('success');
    } catch (error) {
      console.log(error);
    }
  }

  const refreshTableList = async (e) => {
    if (e !== undefined) {
      const params = {
        db: e,
      }
      tableOptions.value = (await getTableList(params)).items;
    } else {
      tableOptions.value = [];
    }
  };

  const initFields = async (db, table, formModel) => {
    if (table !== undefined) {
      const params = {
        db: db,
        table: table,
      }
      formModel.key = `${db}_${table}`;

      const items = (await getColumnList(params)).items;
      fieldOptions.value = items;

      const rows: any = [];
      for (const item of items) {
        const row = {
          field: item.value,
          label: item.value,
          source_field: item.value,
        }
        rows.push(row);
      }
      tableData.value = rows;
    }
  };

  const getSourceDBOptions = async () => {
    const res = await getDBList();
    const options: any = [];
    for (const item of res.items) {
      options.push({
        label: item.label,
        value: item.value,
      });
    }
    sourceDBOptions.value = options;
  };

</script>

<style lang="less" scoped>
  .high-form {
    padding-bottom: 48px;
  }
</style>